1 /* 2 Copyright: Marcelo S. N. Mancini (Hipreme|MrcSnm), 2018 - 2021 3 License: [https://creativecommons.org/licenses/by/4.0/|CC BY-4.0 License]. 4 Authors: Marcelo S. N. Mancini 5 6 Copyright Marcelo S. N. Mancini 2018 - 2021. 7 Distributed under the CC BY-4.0 License. 8 (See accompanying file LICENSE.txt or copy at 9 https://creativecommons.org/licenses/by/4.0/ 10 */ 11 module hip.console.console; 12 import hip.config.opts; 13 import hip.util.string : BigString, String; 14 import hip.util.format; 15 16 17 enum Platforms 18 { 19 default_, 20 desktop, 21 android, 22 uwp, 23 wasm, 24 psvita, 25 appleos, 26 null_ 27 } 28 static enum androidTag = "HipremeEngine"; 29 enum GUI_CONSOLE = true; 30 31 ///If it is inside thread local storage, then, it won't work being called from another thread 32 @nogc __gshared void function(string toPrint) _log; 33 @nogc __gshared void function(string toPrint) _info; 34 @nogc __gshared void function(string toPrint) _warn; 35 @nogc __gshared void function(string toPrint) _err; 36 @nogc __gshared void function(string toPrint) _fatal; 37 version(PSVita) extern(C) void hipVitaPrint(uint length, const(char)* str) @nogc; 38 39 version(UWP){} 40 else version(Windows) 41 version = WindowsNative; 42 43 44 enum WindowsConsoleColors 45 { 46 lightBlue = 1, 47 darkGreen = 2, 48 darkTeal = 3, 49 lightRed = 4, 50 pink = 5, 51 yellow = 6, 52 lightGrey = 7, 53 grey = 8, 54 blue = 9, 55 green = 10, 56 lightTeal = 11, 57 red = 12, 58 white = 15 59 } 60 61 class Console 62 { 63 string name; 64 string[] lines; 65 66 __gshared ushort idCount = 0; 67 ushort id; 68 69 private uint logCounter = 0; 70 __gshared Console DEFAULT; 71 72 string indentation; 73 int indentationCount; 74 int maxLines = 255; 75 int indentationSize = 4; //? Don't know if it should be used instead of \t 76 bool useTab = true; 77 bool isShowing = true; 78 79 80 alias printFuncT = @nogc void function(string); 81 static void install(Platforms p = Platforms.default_, printFuncT printFunc = null) 82 { 83 DEFAULT = new Console("Output", 99); 84 version(WindowsNative) 85 { 86 import core.sys.windows.winbase; 87 import core.sys.windows.wincon; 88 static void* windowsConsole; 89 if(windowsConsole is null) 90 windowsConsole = GetStdHandle(STD_OUTPUT_HANDLE); 91 } 92 switch(p) with(Platforms) 93 { 94 case null_: 95 _log = function(string s){}; 96 _info = _log; 97 _warn = _log; 98 _err = _log; 99 _fatal = _err; 100 break; 101 case android: 102 version(Android) 103 { 104 import hip.jni.helper.androidlog; 105 alias fnType = @nogc void function(string); 106 _log = cast(fnType)function(string s){alogi(androidTag, (s~"\0").ptr);}; 107 _info = _log; 108 _warn = cast(fnType)function(string s){alogw(androidTag, (s~"\0").ptr);}; 109 _err = cast(fnType)function(string s){aloge(androidTag, (s~"\0").ptr);}; 110 _fatal = cast(fnType)function(string s){alogf(androidTag, (s~"\0").ptr);}; 111 } 112 break; 113 case psvita: 114 { 115 version(PSVita) 116 { 117 _log = function(string s){hipVitaPrint(s.length, s.ptr);}; 118 _info = _warn = _err = _fatal = _log; 119 } 120 break; 121 } 122 case wasm: 123 version(WebAssembly) 124 { 125 import arsd.webassembly; 126 import std.stdio; 127 alias nogcfn = @nogc void function(string s); 128 _log = cast(nogcfn)function(string s){writeln(s);}; 129 _fatal = _err = cast(nogcfn)function(string s){eval(q{console.error.apply(null, arguments)}, s);}; 130 _warn = cast(nogcfn)function(string s){eval(q{console.warn.apply(null, arguments)}, s);}; 131 _info = cast(nogcfn)function(string s){eval(q{console.info.apply(null, arguments)}, s);}; 132 } 133 break; 134 case uwp: 135 _log = printFunc; 136 _info = _log; 137 _warn = _log; 138 _err = _log; 139 _fatal = _err; 140 break; 141 case default_: 142 case appleos: 143 case desktop: 144 default: 145 { 146 _log = function(string s) 147 { 148 version(WebAssembly) assert(false, s); 149 else 150 { 151 import core.stdc.stdio; 152 printf("%.*s\n", cast(int)s.length, s.ptr); 153 version(PSVita){} 154 else version(CustomRuntimeTest){} 155 else fflush(stdout); 156 } 157 }; 158 _info = function(string s) 159 { 160 version(WindowsNative){SetConsoleTextAttribute(windowsConsole, WindowsConsoleColors.blue);} 161 _log(s); 162 version(WindowsNative){SetConsoleTextAttribute(windowsConsole, WindowsConsoleColors.white);} 163 }; 164 _warn = function(string s) 165 { 166 version(WindowsNative){SetConsoleTextAttribute(windowsConsole, WindowsConsoleColors.yellow);} 167 _log(s); 168 version(WindowsNative){SetConsoleTextAttribute(windowsConsole, WindowsConsoleColors.white);} 169 }; 170 _err = function(string s) 171 { 172 version(WindowsNative){SetConsoleTextAttribute(windowsConsole, WindowsConsoleColors.red);} 173 _log(s); 174 version(WindowsNative){SetConsoleTextAttribute(windowsConsole, WindowsConsoleColors.white);} 175 }; 176 _fatal = function(string s) 177 { 178 version(WindowsNative){SetConsoleTextAttribute(windowsConsole, WindowsConsoleColors.pink);} 179 _log(s); 180 version(WindowsNative){SetConsoleTextAttribute(windowsConsole, WindowsConsoleColors.white);} 181 }; 182 break; 183 } 184 } 185 } 186 private this(string consoleName, ushort id) 187 { 188 lines = new string[maxLines]; 189 name = consoleName; 190 this.id = id; 191 } 192 193 this(string consoleName) 194 { 195 lines = new string[maxLines]; 196 name = consoleName; 197 id = idCount; 198 idCount++; 199 } 200 201 private void _formatLog(ref string log) 202 { 203 log~= indentation; 204 lines[logCounter++] = log; 205 if(logCounter > maxLines) 206 { 207 lines = lines[1..$]; 208 logCounter--; 209 } 210 } 211 void hipLog(string msg) 212 { 213 lines~= msg; 214 _log(lines[$-1]); 215 } 216 217 218 void log(string msg) @nogc 219 { 220 static if(!HE_NO_LOG && !HE_ERR_ONLY) 221 { 222 //mtx.lock(); 223 _log(msg); 224 //mtx.unlock(); 225 } 226 } 227 228 void logStr(string str) 229 { 230 _info(str); 231 } 232 void info(string msg) 233 { 234 static if(!HE_NO_LOG && !HE_ERR_ONLY) 235 { 236 //mtx.lock(); 237 _info(BigString("INFO: ", msg).toString); 238 //mtx.unlock(); 239 } 240 } 241 242 void warn(string msg) 243 { 244 static if(!HE_NO_LOG && !HE_ERR_ONLY) 245 { 246 //mtx.lock(); 247 _warn(BigString("WARNING: ", msg).toString); 248 //mtx.unlock(); 249 } 250 } 251 252 void error(string msg) 253 { 254 static if(!HE_NO_LOG) 255 { 256 //mtx.lock(); 257 _err(BigString("ERROR: ", msg).toString); 258 //mtx.unlock(); 259 } 260 } 261 262 void fatal(string msg) 263 { 264 static if(!HE_NO_LOG) 265 { 266 //mtx.lock(); 267 _fatal(BigString("FATAL ERROR: ", msg).toString); 268 //mtx.unlock(); 269 } 270 } 271 272 void indent() 273 { 274 //mtx.lock(); 275 if(useTab) 276 indentation~= "\t"; 277 else 278 for(int i = 0; i < indentationSize; i++) 279 indentation~= " "; 280 indentationCount++; 281 //mtx.unlock(); 282 } 283 284 void unindent() 285 { 286 //mtx.lock(); 287 if(useTab) 288 indentation = indentation[1..$]; 289 else 290 indentation = indentation[indentationSize..$]; 291 indentationCount--; 292 //mtx.unlock(); 293 } 294 }